package com.weipt.rabbitmq;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;


/**5
 * 路由模式
 * routingkey模式，支持多对多绑定队列
 * 后续根据路由key命中后，往相应的队列发消息
 * topic模式在此基础上，增加了模糊匹配
 */
public class HelloDirect {

    public static final String QUEUE_NAME1 = "hello-direct-queue1";

    public static final String QUEUE_NAME2 = "hello-direct-queue2";

    public static final String QUEUE_NAME3 = "hello-direct-queue3";
    public static final String EXCHANGE_NAME = "hello-direct-exchange";

    public static final String ROUTING_KEY1 = "hello-direct-routingkey1";

    public static final String ROUTING_KEY2 = "hello-direct-routingkey2";

    public static final String EXCHANGE_TYPE = "direct";

    public static void main(String[] args) throws IOException, TimeoutException {
        publish("test direct");
        consume();
    }

    public static void publish(String msg) throws IOException, TimeoutException {
        Connection mqConn = ConnectionUtils.getMqConn();
        Channel channel = mqConn.createChannel(); //创建一个新的管道
        channel.exchangeDeclare(EXCHANGE_NAME, EXCHANGE_TYPE);    //创建一个新的交换机exchange，一般项目中exchange都会提前规划好，此处仅演示
        //通道绑定对应消息队列
        //参数1:  队列名称 如果队列不存在自动创建
        //参数2:  用来定义队列特性是否要持久化 true 持久化队列   false 不持久化
        //参数3:  exclusive 是否独占队列，表示声明的当前队列只允许当前的连接所使用  true 独占队列   false  不独占
        //参数4:  autoDelete: 是否在消费完成后自动删除队列  true 自动删除  false 不自动删除
        //参数5:  额外附加参数

        //一个routingkey可以绑定多个队列
        channel.queueDeclare(QUEUE_NAME1, false, false, false, null);
        channel.queueBind(QUEUE_NAME1, EXCHANGE_NAME, ROUTING_KEY1);//绑定之后，如果修改了routingkey，相当于增加绑定关系，而不是覆盖

        channel.queueDeclare(QUEUE_NAME2, false, false, false, null);
        channel.queueBind(QUEUE_NAME2, EXCHANGE_NAME, ROUTING_KEY1);//绑定之后，如果修改了routingkey，相当于增加绑定关系，而不是覆盖

        channel.queueDeclare(QUEUE_NAME3, false, false, false, null);
        channel.queueBind(QUEUE_NAME3, EXCHANGE_NAME, ROUTING_KEY1);//绑定之后，如果修改了routingkey，相当于增加绑定关系，而不是覆盖

        //一个队列，也可以绑定多个routingkey
        channel.queueBind(QUEUE_NAME3, EXCHANGE_NAME, ROUTING_KEY2);//绑定之后，如果修改了routingkey，相当于增加绑定关系，而不是覆盖

        //因为rabbitmq是长连接，相当于一个连接中可以创建多个管道就行通讯，类比http长连接
        //所有的消息不能直接由channel发给queue，必须要经过exchange，如果不指定，则走默认的exchage，默认的是direct模式。非direct模式无法走默认
        //发key1,123队列都收到，  发key2,3收到
        channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY1,  MessageProperties.PERSISTENT_TEXT_PLAIN, msg.getBytes());
        //关闭连接
        channel.close();
        mqConn.close();
    }

    public static void consume() throws IOException {
        Connection mqConn = ConnectionUtils.getMqConn();
        Channel channel = mqConn.createChannel();
        channel.basicConsume(QUEUE_NAME1, true, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("handleDelivery:"+consumerTag);
                System.out.println("可以通过重写handleDelivery方法，获取queue中的消息。消息内容："+new String(body));
            }
        });
        //消费端连接与同道不用关闭，一直处于监听状态
        //channel.close();
        //mqConn.close();
    }
}
